#include "SANClient.h"


SANClient::SANClient()
{
    iCount = 0;
    iTotDelay = 0;
}

SANClient::~SANClient()
{
    fclose(iFp);
    close(iClientSockFd);
}

bool SANClient::OpenFile(std::string aFileName)
{
    const char *name = aFileName.c_str();
    iFp = fopen(name, "r");
    if(iFp != NULL)
        return true;
    else
        return false;
}

void SANClient::SetDestnPort(int aPort)
{
    iPort = aPort;
}

void SANClient::SetDestnIp(std::string aIp)
{
    iIp = aIp;
}

void SANClient::SetDelay(double aDelay)
{
    //iDelay.tv_sec = aDelay;
    //iDelay.tv_nsec = aDelay * 1000000000;
    //qDebug("idelay int %d", iDelay.tv_sec);
}

bool SANClient::SetupConnection()
{
    const char *ip = iIp.c_str();
    iClientSockFd = socket(AF_INET, SOCK_STREAM, 0);
    iServAddr.sin_addr.s_addr = inet_addr(ip);
    iServAddr.sin_port = htons(iPort);
    iServAddr.sin_family = AF_INET;

    if(iClientSockFd > 0)
        return true;
    else
        return false;

}

bool SANClient::ConnectToServer()
{
    if(::connect(iClientSockFd, (struct sockaddr*)&iServAddr, sizeof(iServAddr) ) < 0)
        return false;
    else
        return true;
}

void SANClient::SetDistribution(int aDistribution)
{
    iDistribution = aDistribution;
}

int SANClient::GetDistribution()
{
    return iDistribution;
}

void SANClient::SetSendRate(int aSendRate)
{
    iSendRate = aSendRate;
}

int SANClient::GetSendRate()
{
    return iSendRate;
}

long double SANClient::GetTotDelay()
{
    return iTotDelay;
}

void SANClient::SendData()
{

    int len = 0;
    char *buf = (char*)calloc(DATA_LEN, sizeof(char));
    double d, delay;

    while(!feof(iFp))
    {

        if(iDistribution == KPoisson)
        {
            d = -1 * log(drand48());
            delay = (d * DATA_LEN )/(iSendRate * 1000);
            qDebug("delay %f", delay);
            iTotDelay += delay;
            qDebug("totaldelay %f", iTotDelay);
            //in micro secs
            iUSleep = delay * 1000000;

        }
        len = fread(buf, sizeof(char), DATA_LEN, iFp);
        //introduce sleep here if needed to control send rate
        usleep(iUSleep);
        send(iClientSockFd, buf, len, 0);
        iCount++;

        //to show sent data in UI
        //emit EmitDataSent(buf);
    }
}

int SANClient::GetCount()
{
    return iCount;
}

void SANClient::run(void)
{

    SendData();
}

SANReceive::SANReceive()
{
    iBuf = (char*)calloc(DATA_LEN, sizeof(char));
    iLen = 0;
    iCount = 0;
}

SANReceive::~SANReceive()
{
    if(iBuf)
        free(iBuf);
    close(iServSockFd);
    close(iBlankSockFd);
}

void SANReceive::SetPort(int aPort)
{
    iPort = aPort;
}

int SANReceive::GetPort()
{
    return iPort;
}

bool SANReceive::SetupConnection()
{
    iServSockFd = socket(AF_INET, SOCK_STREAM, 0);
    iClientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    iClientAddr.sin_family = AF_INET;
    iClientAddr.sin_port = htons(iPort);

    if(iServSockFd > 0)
        return true;
    else
        return false;
}

bool SANReceive::StartServer()
{
    if(bind(iServSockFd, (struct sockaddr*)&iClientAddr, sizeof(iClientAddr)) < 0)
        return false;

    if(listen(iServSockFd, 1) < 0)
        return false;

    return true;

}

int SANReceive::AcceptConnections()
{
    int blankfd = accept(iServSockFd, 0, 0);
    if(blankfd < 0)
        return -1;
    else
        return blankfd;
}

void SANReceive::run(void)
{
    bool status = true;
    if(SetupConnection() == false)
    {
        status = false;
        emit EmitServerStart(false);
    }

    status = StartServer();
    if(status == false)
    {
        emit EmitServerStart(false);
    }
    else
    {
        emit EmitServerStart(true);

        iBlankSockFd = AcceptConnections();
        if(iBlankSockFd > 0)
        {
            emit EmitClientAccepted(true);
            RecvData();
        }
        else
            emit EmitClientAccepted(false);
    }

}

int SANReceive::GetCount()
{
    return iCount;
}

void SANReceive::RecvData()
{
    while(true)
    {
        bzero(iBuf, DATA_LEN);
        iLen = 0;
        iLen = recv(iBlankSockFd, (char*)iBuf, DATA_LEN, 0);
        if(iLen > 0)
        {
              iCount++;

              //to display sorted and received data in UI
              //QString temp(iBuf);
              //emit EmitDisplaySortedData(temp);
        }
    }
}
